package com.tsfyun.scm.support.singlewindow;

import com.anji.captcha.util.FileCopyUtils;
import com.google.common.base.Stopwatch;
import com.tsfyun.common.base.dto.DeclareBizSendDTO;
import com.tsfyun.common.base.dto.ExportFileDTO;
import com.tsfyun.common.base.enums.BillTypeEnum;
import com.tsfyun.common.base.enums.TransactionModeEnum;
import com.tsfyun.common.base.enums.singlewindow.EdocRealationEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.util.*;
import com.tsfyun.common.base.validator.ValidatorUtils;
import com.tsfyun.scm.dto.declaration.singlewindow.declare.*;
import com.tsfyun.scm.entity.customs.Declaration;
import com.tsfyun.scm.entity.system.Subject;
import com.tsfyun.scm.entity.system.SubjectOverseas;
import com.tsfyun.scm.service.customs.IDeclarationPdfService;
import com.tsfyun.scm.service.customs.IDeclarationService;
import com.tsfyun.scm.service.file.IExportFileService;
import com.tsfyun.scm.service.system.ISubjectOverseasService;
import com.tsfyun.scm.service.system.ISubjectService;
import com.tsfyun.scm.vo.customs.ContractPlusVO;
import com.tsfyun.scm.vo.customs.DeclarationMemberVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 单一窗口对接服务类
 * @since Created in 2020/5/7 09:33
 */
@RefreshScope
@Slf4j
@Component
public class DeclareBiz {

    @Autowired
    private ISubjectService subjectService;
    @Autowired
    private ISubjectOverseasService subjectOverseasService;
    @Autowired
    private IExportFileService exportFileService;
    @Autowired
    private IDeclarationPdfService declarationPdfService;
    @Autowired
    private IDeclarationService declarationService;


    //文件存放目录
    @Value(value = "${file.directory}")
    private String fileDirectory;
    @Value(value = "${entry.unit.name}")
    private String entryUnitName;
    @Value(value = "${entry.unit.code}")
    private String entryUnitCode;
    @Value(value = "${entry.unit.scc}")
    private String entryUnitScc;


    //报关单暂存版本
    private static final Float DECLARE_TEMP_SAVE_VERSION = 4.6F;

    private static final String BUSINESS_TYPE_PATH = "single_window";

    private static final String DECLARETION_TEMP_SAVE = "declaretion_temp_save";

    //报关单暂存-进出口通用
    public DeclareBizSendDTO declareTempSave(String tenant, Declaration declaration, List<DeclarationMemberVO> members) {
        //组装单一窗口报文
        //验证
        //发送
        Stopwatch stopwatch = Stopwatch.createStarted();
        DecMessage decMessage = new DecMessage();
        //版本
        decMessage.setVersion(DECLARE_TEMP_SAVE_VERSION);
        //报关单表头
        DecHeadType docHeadType = new DecHeadType();
        //数据中心统一编号
        docHeadType.setSeqNo("");
        //进出口标志（I-进口；E-出口）
        docHeadType.setIEFlag(Objects.equals(declaration.getBillType(), BillTypeEnum.IMP.getCode()) ? "I" : "E");

        //申报单位信息
        docHeadType.setAgentCode(declaration.getAgentCode());//申报单位代码（组织机构代码）
        docHeadType.setAgentName(declaration.getAgentName());//10位海关代码
        docHeadType.setAgentCodeScc(declaration.getAgentScc());//18位社会信用代码
        docHeadType.setDeclCiqCode("");//申报单位检验检疫编码

        //境内收发货人
        Subject trade = subjectService.getById(declaration.getSubjectId());
        docHeadType.setTradeName(trade.getName()); //境内收发货人名称
        docHeadType.setTradeCode(trade.getCustomsCode());//10位海关代码
        TsfPreconditions.checkArgument((StringUtils.isNotEmpty(docHeadType.getTradeCode())&&docHeadType.getTradeCode().length() == 10),new ServiceException(String.format("请先维护【%s】10位海关代码",docHeadType.getTradeName())));
        docHeadType.setTradeCoScc(trade.getSocialNo()); //18位社会信用代码
        TsfPreconditions.checkArgument((StringUtils.isNotEmpty(docHeadType.getTradeCoScc())&&docHeadType.getTradeCoScc().length() == 18),new ServiceException(String.format("请先维护【%s】18位社会信用代码",docHeadType.getTradeName())));
        docHeadType.setTradeCiqCode(""); //境内收发货人检验检疫编码

        docHeadType.setOverseasConsignorCode("");//境外发货人代码
        docHeadType.setOverseasConsignorCname("");//境外发货人名称
        docHeadType.setOverseasConsignorEname("");//境外发货人名称（外文）
        docHeadType.setOverseasConsignorAddr("");//境外发货人地址
        docHeadType.setOverseasConsigneeCode("");//境外收货人代码
        docHeadType.setOverseasConsigneeEname("");//境外收货人名称（外文）
        docHeadType.setDomesticConsigneeEname("");//境内收发货人名称（外文）
        if("I".equals(docHeadType.getIeFlag())){
            SubjectOverseas overseas = subjectOverseasService.getById(declaration.getSubjectOverseasId());
            Optional.ofNullable(overseas).orElseThrow(()->new ServiceException("境外收发货人不存在"));
            //进口-境外发货人
            docHeadType.setOverseasConsignorCname(StringUtils.removeSpecialSymbol(overseas.getNameCn()));//境外发货人名称
            docHeadType.setOverseasConsignorEname(overseas.getName());//境外发货人名称（外文）
            docHeadType.setOverseasConsignorAddr(StringUtils.removeSpecialSymbol(overseas.getAddress()));//境外发货人地址
        }else{
            //出口-境外收货人
            SubjectOverseas overseas = subjectOverseasService.getById(declaration.getSubjectOverseasId());
            if(Objects.nonNull(overseas)) {
                docHeadType.setOverseasConsigneeEname(overseas.getName());//境外收货人名称（外文）
            } else {
                docHeadType.setOverseasConsigneeEname(declaration.getSubjectOverseasName());//境外收货人名称（外文）
            }
        }

        //消费使用单位/生产销售单位信息
        docHeadType.setOwnerName(declaration.getOwnerName());//名称
        docHeadType.setOwnerCode(declaration.getOwnerCode());//10位海关代码
        docHeadType.setOwnerCodeScc(declaration.getOwnerScc());//18位社会信用代码
        docHeadType.setOwnerCiqCode(""); //消费使用/生产销售单位校验检疫编码

        //录入单位信息
        docHeadType.setCopName(entryUnitName);//录入单位名称
        docHeadType.setCopCode(entryUnitCode);//10位海关代码
        docHeadType.setCopCodeScc(entryUnitScc);//18位社会信用代码
        docHeadType.setTypistNo(""); //录入员IC卡号
        docHeadType.setInputerName(""); //录入人名称


        //报关/转关关系标志 0-一般报关单，1-转关提前报关单
        docHeadType.setDeclTrnRel("0");
        //报关标志 1-普通报关；3-北方转关提前；5-南方转关提前；6-普通报关，运输工具名称以‘◎’
        docHeadType.setEdiId("1");
        //批准文号
        docHeadType.setApprNo("");
        //提单号 (提运单号（仓单）)
        docHeadType.setBillNo(declaration.getBillNo());
        TsfPreconditions.checkArgument(StringUtils.isNotEmpty(docHeadType.getBillNo()),new ServiceException("提运单号不能为空"));
        //合同号
        docHeadType.setContrNo(declaration.getContrNo());
        //主管海关（申报地海关）
        docHeadType.setCustomMaster(declaration.getCustomMasterCode());
        //征免性质
        docHeadType.setCutMode(declaration.getCutModeCode());
        //数据源
        docHeadType.setDataSource("");
        //进口经停港/出口指运港
        docHeadType.setDistinatePort(declaration.getDistinatePortCode());

        //运费币制
        docHeadType.setFeeCurr("");
        //运费标记
        docHeadType.setFeeMark("");
        //运费/率
        docHeadType.setFeeRate("");
        if(StringUtils.isNotEmpty(declaration.getTransCosts())){
            String[] transCosts = declaration.getTransCosts().split("/");
            if(new BigDecimal(transCosts[1]).compareTo(BigDecimal.ZERO)==1){
                //运费币制
                docHeadType.setFeeCurr("000".equals(transCosts[0])?"":transCosts[0]);
                //运费标记
                docHeadType.setFeeMark(transCosts[2]);
                //运费/率
                docHeadType.setFeeRate(transCosts[1]);
            }
        }
        //保险费币制
        docHeadType.setInsurCurr("");
        //保险费标记
        docHeadType.setInsurMark("");
        //保险费、率
        docHeadType.setInsurRate("");
        if(StringUtils.isNotEmpty(declaration.getInsuranceCosts())){
            String[] insuranceCosts = declaration.getInsuranceCosts().split("/");
            if(new BigDecimal(insuranceCosts[1]).compareTo(BigDecimal.ZERO)==1){
                //保险费币制
                docHeadType.setInsurCurr("000".equals(insuranceCosts[0])?"":insuranceCosts[0]);
                //保险费标记
                docHeadType.setInsurMark(insuranceCosts[2]);
                //保险费、率
                docHeadType.setInsurRate(insuranceCosts[1]);
            }
        }
        //杂费币制
        docHeadType.setOtherCurr("");
        //杂费标记
        docHeadType.setOtherMark("");
        //杂费、率
        docHeadType.setOtherRate("");
        if(StringUtils.isNotEmpty(declaration.getMiscCosts())){
            String[] miscCosts = declaration.getMiscCosts().split("/");
            if(new BigDecimal(miscCosts[1]).compareTo(BigDecimal.ZERO)==1){
                //杂费币制
                docHeadType.setOtherCurr("000".equals(miscCosts[0])?"":miscCosts[0]);
                //杂费标记
                docHeadType.setOtherMark(miscCosts[2]);
                //杂费、率
                docHeadType.setOtherRate(miscCosts[1]);
            }
        }
        //毛重（不足1按1算）
        docHeadType.setGrossWet(String.valueOf(BigDecimal.ONE.compareTo(declaration.getGrossWt()) == 1 ? BigDecimal.ONE : declaration.getGrossWt()));
        //进出口日期
        docHeadType.setIEDate(LocalDateTimeUtils.formatTime(declaration.getImportDate(),"yyyyMMdd"));
        //进出境关别
        docHeadType.setIEPort(declaration.getIePortCode());

        //许可证编号
        docHeadType.setLicenseNo(StringUtils.removeSpecialSymbol(declaration.getLicenseNo()));
        //备案号
        docHeadType.setManualNo(StringUtils.removeSpecialSymbol(declaration.getRecordNo()));
        //净重
        docHeadType.setNetWt(declaration.getNetWt().toString());
        //备注
        docHeadType.setNoteS("");

        //件数
        TsfPreconditions.checkArgument(Objects.nonNull(declaration.getPackNo()),new ServiceException("件数不能为空"));
        docHeadType.setPackNo(declaration.getPackNo().toString());

        //进口启运国、出口运抵国
        docHeadType.setTradeCountry(declaration.getCusTradeCountryCode());
        //监管方式
        docHeadType.setTradeMode(declaration.getSupvModeCdde());
        //运输方式代码
        docHeadType.setTrafMode(declaration.getCusTrafModeCode());
        //运输工具代码及名称
        //docHeadType.setTrafName(declaration.getCusTrafModeName());
        //docHeadType.setTrafMode("");
        docHeadType.setTrafName("");
        //成交方式
        switch (TransactionModeEnum.of(declaration.getTransactionMode())) {
            case CIF:
                docHeadType.setTransMode("1");
                break;
            case FOB:
                docHeadType.setTransMode("3");
                break;
            default:
                throw new ServiceException("成交方式暂不支持，请联系管理员");
        }
        //单据类型
        docHeadType.setType("");
        //包装种类
        docHeadType.setWrapType(declaration.getWrapTypeCode());
        //海关编号
        docHeadType.setEntryId("");
        //预录入编号
        docHeadType.setPreEntryId("");
        //申报人标识
        docHeadType.setPartenerID("");
        //风险评估参数
        docHeadType.setRisk("");
        //关联单据号
        docHeadType.setTgdNo("");

        //报关单类型 0-普通报关单；L-带报关单清单的报关单，W-无纸化报关类型 D-既是清单又是无纸报关的情况 M-无纸化通关
        docHeadType.setEntryType("M");

        //申报人标识
        docHeadType.setPartenerID("");
        //担保验放标志 1-是0-否
        docHeadType.setChkSurety("");
        //备案清单类型 自贸区特有的类型 1-普通备案 2-先进区后报关  3-分送集报备案清单  4-分送集报报关单
        docHeadType.setBillType("");
        //承诺事项 固定为否
        List<String> promiseItmes = Arrays.asList("0","0","0");
        docHeadType.setPromiseItmes(String.join("",promiseItmes));
        //贸易国别
        docHeadType.setTradeAreaCode(declaration.getCusTradeNationCode());
        //查验标识
        docHeadType.setCheckFlow("");
        //税收征管标记
        docHeadType.setTaxAaminMark("");
        //标记唛码
        docHeadType.setMarkNo("");
        //进口启运港代码，出口无
        if("I".equals(docHeadType.getIeFlag())) {
            docHeadType.setDespPortCode(declaration.getDestPortCode());
        } else {
            docHeadType.setDespPortCode("");
        }
        //进口入境口岸代码/出口离境口岸
        docHeadType.setEntyPortCode(declaration.getCiqEntyPortCode());
        //存放地点
        docHeadType.setGoodsPlace(declaration.getGoodsPlace());
        //B/L号
        docHeadType.setBLNo("");
        //口岸校验检疫机关
        docHeadType.setInspOrgCode("");
        //特种业务标识
        docHeadType.setSpecDeclFlag("");
        //目的地校验检疫机关
        docHeadType.setPurpOrgCode("");
        //启运日期，格式yyyyMMdd
        docHeadType.setDespDate("");
        //卸毕日期，格式yyyyMMdd
        docHeadType.setCmplDschrgDt("");
        //关联理由
        docHeadType.setCorrelationReasonFlag("");
        //领证机关
        docHeadType.setVsaOrgCode("");
        //原集装箱标识
        docHeadType.setOrigBoxFlag("");
        //申报人姓名
        docHeadType.setDeclareName("");
        //无其他包装
        docHeadType.setNoOtherPack("");
        //检验检疫受理机关
        docHeadType.setOrgCode("");

        //关联号码
        docHeadType.setCorrelationNo("");
        //EDI申报标识
        docHeadType.setEdiRemark("");
        //EDI申报标识2
        docHeadType.setEdiRemark2("");


        //基本信息
        decMessage.setDecHead(docHeadType);

        //明细信息
        DecMessage.DecLists decLists = new DecMessage.DecLists();
        List<DecListItemType> decListItemTypes = decLists.getDecList();
        for (int i = 0,size = members.size();i < size;i++) {
            DeclarationMemberVO declarationMember = members.get(i);
            DecListItemType decListItemType = new DecListItemType();
            decListItemType.setGNo(String.valueOf(i + 1));
            //归类标识
            decListItemType.setClassMark("");
            //商品编号
            decListItemType.setCodeTS(declarationMember.getHsCode());
            //备案序号
            decListItemType.setContrItem("");
            //申报单价
            decListItemType.setDeclPrice(declarationMember.getUnitPrice().toString());
            //征免方式（照章征免）
            decListItemType.setDutyMode(declarationMember.getDutyMode());
            //申报计量单位与法定单位比例因子
            decListItemType.setFactor("");
            //商品规格、型号
            String declareSpec = StringUtils.removeSpecialSymbol(declarationMember.getDeclareSpec());
            if(declareSpec.endsWith("|")) {
                declareSpec = declareSpec.concat(" ");
            }
            decListItemType.setGModel(declareSpec);
            //商品名称
            decListItemType.setGName(declarationMember.getName());
            //商品序号
            decListItemType.setGNo(String.valueOf(i + 1));
            //原产国编码
            decListItemType.setOriginCountry(declarationMember.getCountry());
            //成交币制
            decListItemType.setTradeCurr(declarationMember.getCurrencyId());
            //申报总价
            decListItemType.setDeclTotal(declarationMember.getTotalPrice().toString());
            //成交数量
            decListItemType.setGQty(declarationMember.getQuantity().toString());
            //法一数量
            decListItemType.setFirstQty(StringUtils.removeSpecialSymbol(declarationMember.getQuantity1()));
            //法二数量
            decListItemType.setSecondQty(StringUtils.removeSpecialSymbol(declarationMember.getQuantity2()));
            //成交单位
            decListItemType.setGUnit(declarationMember.getUnitCode());
            //法一单位
            decListItemType.setFirstUnit(StringUtils.removeSpecialSymbol(declarationMember.getUnit1Code()));
            //法二单位
            decListItemType.setSecondUnit(StringUtils.removeSpecialSymbol(declarationMember.getUnit2Code()));
            //用途/生产厂家
            decListItemType.setUseTo("");
            //工缴费
            decListItemType.setWorkUsd("");
            //货号
            decListItemType.setExgNo("");
            //版本号
            decListItemType.setExgVersion("");
            //最终目的国（地区）
            decListItemType.setDestinationCountry(declarationMember.getDestinationCountry());
            //检验检疫编码
            decListItemType.setCiqCode("");
            //商品英文名称
            decListItemType.setDeclGoodsEname("");
            //原产地区代码
            decListItemType.setOrigPlaceCode("");
            //用途代码
            decListItemType.setPurpose("");
            //产品有效期
            decListItemType.setProdValidDt("");
            //货物属性代码
            decListItemType.setGoodsAttr("");
            //成分/原料/组份
            decListItemType.setStuff("");
            //UN编码
            decListItemType.setUncode("");
            //危险货物名称
            decListItemType.setDangName("");
            //危包类别
            decListItemType.setDangPackType("");
            //危包规格
            decListItemType.setDangPackSpec("");
            //境外生产企业名称
            decListItemType.setEngManEntCnm("");
            //非危险化学品
            decListItemType.setNoDangFlag("");
            //进口目的地代码
            decListItemType.setDestCode(declarationMember.getCiqDestCode());
            //校验检疫货物规格
            decListItemType.setGoodsSpec("");
            //货物型号
            decListItemType.setGoodsModel("");
            //货物品牌
            decListItemType.setGoodsBrand("");
            //生产日期
            decListItemType.setProduceDate("");
            //生产批号
            decListItemType.setProdBatchNo("");
            //进口-境内目的地，出口-境内货源地
            decListItemType.setDistrictCode(declarationMember.getDistrictCode());
            //校验检疫名称
            decListItemType.setCiqName("");
            //生产单位注册号
            decListItemType.setMnufctrRegNo("");
            //生产单位名称
            decListItemType.setMnufctrRegName("");
            decListItemTypes.add(decListItemType);
        }
        decMessage.setDecLists(decLists);

        //报关单集装箱

        //报关自由文本
        DecFreeTxtType decFreeTxtType = new DecFreeTxtType();
        decFreeTxtType.setRelId("");
        decFreeTxtType.setRelManNo("");
        decFreeTxtType.setBonNo("");
        decFreeTxtType.setDecBpNo("");
        decFreeTxtType.setCusFie("");
        decFreeTxtType.setDecNo("");
        decFreeTxtType.setVoyNo(declaration.getCusVoyageNo());

        decMessage.setDecFreeTxt(decFreeTxtType);

        //电子随附单据关联关系信息
        List<EdocRealationType> edocRealationTypes = decMessage.getEdocRealation();
        //##################发票#################
        EdocRealationType invoiceEdocRealationType =  new EdocRealationType();
        invoiceEdocRealationType.setEdocId(String.valueOf(System.currentTimeMillis()));
        //随附单证类别
        invoiceEdocRealationType.setEdocCode(EdocRealationEnum.INVOICE.getCode());
        //操作说明
        invoiceEdocRealationType.setOpNote(EdocRealationEnum.INVOICE.getName());
        //非结构化文档，PDF为US
        invoiceEdocRealationType.setEdocFomatType("US");
        //随附单证文件企业名
        String invoiceFileName = String.format("%s_INVOICE.pdf",declaration.getDocNo());
        invoiceEdocRealationType.setEdocCopId(invoiceFileName);
        //所属单位海关编号
        invoiceEdocRealationType.setEdocOwnerCode(declaration.getAgentCode());
        //所属单位名称
        invoiceEdocRealationType.setEdocOwnerName(declaration.getAgentName());
        //随附单据文件大小
        invoiceEdocRealationType.setEdocSize("100");
        edocRealationTypes.add(invoiceEdocRealationType);

        //##################装箱单#####################
        EdocRealationType packageEdocRealationType =  new EdocRealationType();
        packageEdocRealationType.setEdocId(String.valueOf(System.currentTimeMillis()));
        //随附单证类别
        packageEdocRealationType.setEdocCode(EdocRealationEnum.PACKINGLIST.getCode());
        //操作说明
        packageEdocRealationType.setOpNote(EdocRealationEnum.PACKINGLIST.getName());
        packageEdocRealationType.setEdocFomatType("US");
        //随附单证文件企业名
        String packingFileName = String.format("%s_PACKINGLIST.pdf",declaration.getDocNo());
        packageEdocRealationType.setEdocCopId(packingFileName);
        //所属单位海关编号
        packageEdocRealationType.setEdocOwnerCode(declaration.getAgentCode());
        //所属单位名称
        packageEdocRealationType.setEdocOwnerName(declaration.getAgentName());
        //随附单据文件大小
        packageEdocRealationType.setEdocSize("100");
        edocRealationTypes.add(packageEdocRealationType);

        //#####################合同####################
        EdocRealationType contractEdocRealationType =  new EdocRealationType();
        contractEdocRealationType.setEdocId(String.valueOf(System.currentTimeMillis()));
        //随附单证类别
        contractEdocRealationType.setEdocCode(EdocRealationEnum.CONTRACT.getCode());
        //操作说明
        contractEdocRealationType.setOpNote(EdocRealationEnum.CONTRACT.getName());
        contractEdocRealationType.setEdocFomatType("US");
        //随附单证文件企业名
        String contractFileName = String.format("%s_CONTRACT.pdf",declaration.getDocNo());
        contractEdocRealationType.setEdocCopId(contractFileName);
        //所属单位海关编号
        contractEdocRealationType.setEdocOwnerCode(declaration.getAgentCode());
        //所属单位名称
        contractEdocRealationType.setEdocOwnerName(declaration.getAgentName());
        //随附单据文件大小
        contractEdocRealationType.setEdocSize("100");
        edocRealationTypes.add(contractEdocRealationType);

        String shippingFileName = String.format("%s_SHIPPING.pdf",declaration.getDocNo());
        if("fob".equals(declaration.getTransactionMode())){
            //#####################运费协议####################
            EdocRealationType shippingEdocRealationType =  new EdocRealationType();
            shippingEdocRealationType.setEdocId(String.valueOf(System.currentTimeMillis()));
            //随附单证类别
            shippingEdocRealationType.setEdocCode(EdocRealationEnum.COMPANY_PROVE_DATA.getCode());
            //操作说明
            shippingEdocRealationType.setOpNote(EdocRealationEnum.COMPANY_PROVE_DATA.toString());
            shippingEdocRealationType.setEdocFomatType("US");
            //随附单证文件企业名
            shippingEdocRealationType.setEdocCopId(shippingFileName);
            //所属单位海关编号
            shippingEdocRealationType.setEdocOwnerCode(declaration.getAgentCode());
            //所属单位名称
            shippingEdocRealationType.setEdocOwnerName(declaration.getAgentName());
            //随附单据文件大小
            shippingEdocRealationType.setEdocSize("100");
            edocRealationTypes.add(shippingEdocRealationType);
        }

        //中港运输协议
        String transportFileName = String.format("%s_TRANSPORT.pdf",declaration.getDocNo());
        EdocRealationType transportEdocRealationType =  new EdocRealationType();
        transportEdocRealationType.setEdocId(String.valueOf(System.currentTimeMillis()));
        //随附单证类别
        transportEdocRealationType.setEdocCode(EdocRealationEnum.COMPANY_OTHER_DATA.getCode());
        //操作说明
        transportEdocRealationType.setOpNote(EdocRealationEnum.COMPANY_OTHER_DATA.toString());
        transportEdocRealationType.setEdocFomatType("US");
        //随附单证文件企业名
        transportEdocRealationType.setEdocCopId(transportFileName);
        //所属单位海关编号
        transportEdocRealationType.setEdocOwnerCode(declaration.getAgentCode());
        //所属单位名称
        transportEdocRealationType.setEdocOwnerName(declaration.getAgentName());
        //随附单据文件大小
        transportEdocRealationType.setEdocSize("100");
        edocRealationTypes.add(transportEdocRealationType);


        DecSign decSign = new DecSign();
        //G-报关单暂存
        decSign.setOperType("G");
        decSign.setIcCode("");
        decSign.setCopCode(entryUnitCode);
        decSign.setOperName(entryUnitName);
        decSign.setSign("");
        decSign.setSignDate("");
        decSign.setClientSeqNo(String.format("%s_%s",tenant,declaration.getDocNo()));
        decSign.setCertificate("");
        //签名人分类 1:录入人；2:申报人
        decSign.setDomainId("1");
        //对应清单统一编号 如果报关单有对应的清单填报关单对应的清单统一编号；如果没有清单填企业自编统一编号
        decSign.setBillSeqNo(String.format("%s_%s",tenant,declaration.getDocNo()));
        decSign.setHostId("");
        decSign.setNote("");

        decMessage.setDecSign(decSign);

        //校验参数
        ValidatorUtils.validateEntityWithRow(decMessage);

        //生成本地临时目录-压缩后删除
        String path = fileDirectory + String.format("%s/%s/%s/%s/%s", tenant,BUSINESS_TYPE_PATH,DECLARETION_TEMP_SAVE,
                declaration.getBillType(),StringUtils.UUID());
        //生成报文
        XmlUtils.convertToXml(decMessage,path, declaration.getId().toString());
        log.info("报关单【{}】生成xml报文文件耗时【{}】秒",declaration.getDocNo(),stopwatch.elapsed(TimeUnit.SECONDS));
        //将生成的文件转移到单一窗口扫描目录，并压缩
        String zipPath = fileDirectory + String.format("%s/%s/%s/%s/", tenant,BUSINESS_TYPE_PATH,DECLARETION_TEMP_SAVE,declaration.getBillType());
        String sysFileName = tenant+"_"+declaration.getDocNo()+"_"+StringUtils.UUID()+ ".zip";
        //合同、箱单、发票
        ContractPlusVO vo = declarationService.contractData(declaration.getId());
        //生成合同
        declarationPdfService.createContractPdf(vo,Boolean.TRUE,path,contractFileName);
        //箱单
        declarationPdfService.createPackingPdf(vo,Boolean.TRUE,path,packingFileName);
        //发票
        declarationPdfService.createInvoicePdf(vo,Boolean.TRUE,path,invoiceFileName);
        // 运输保险协议和中港运输协议 进口需要 暂不传
        /*
        if(Objects.equals(declaration.getBillType(),BillTypeEnum.IMP.getCode())) {
            // 运费保险协议
            if("fob".equals(declaration.getTransactionMode())){
                ClassPathResource resource = new ClassPathResource("pdf/SHIPPING.pdf");
                try{
                    FileCopyUtils.copy(IOUtils.toByteArray(resource.getInputStream()),new File(path.concat(File.separator).concat(shippingFileName)));
                }catch (Exception e){
                    log.error("运输保险协议文件复制失败",e);
                    throw new ServiceException("未找到运费保险协议");
                }
            }
            //中港运输协议
            try{
                ClassPathResource transportResource = new ClassPathResource("pdf/TRANSPORT.pdf");
                FileCopyUtils.copy(IOUtils.toByteArray(transportResource.getInputStream()),new File(path.concat(File.separator).concat(transportFileName)));
            }catch (Exception e){
                log.error("中港运输协议文件复制失败",e);
                throw new ServiceException("未找到中港运输协议");
            }
        }
         */
        try {
            FileUtil.execute(path,zipPath + sysFileName);
            log.info("报关单【{}】压缩xml报文文件完成",declaration.getDocNo());
        } catch (IOException e) {
            log.error("压缩单一窗口报文文件异常",e);
            throw new ServiceException("压缩报文文件异常，请稍后再试");
        }
        //删除原临时文件
        log.info("报关单【{}】删除原始文件完成",declaration.getDocNo());
        FileUtil.deleteDir(new File(path));

        //写入导出下载
        ExportFileDTO exportFileDTO = new ExportFileDTO();
        exportFileDTO.setPath(zipPath + sysFileName);
        exportFileDTO.setFileName(sysFileName);
        exportFileDTO.setOnce(Boolean.TRUE);
        exportFileDTO.setOperator("系统自动生成");

        Long fileId = exportFileService.save(exportFileDTO);
        DeclareBizSendDTO sendDTO = new DeclareBizSendDTO();
        sendDTO.setTenant(tenant);
        sendDTO.setType("declare");
        sendDTO.setDownUrl("http://159.75.229.63:9099/scm/export/down?id="+fileId);
        sendDTO.setFileName(sysFileName);
        return sendDTO;
    }

}
